/**
 * Copyright (C) 2018-2020
 * All rights reserved, Designed By www.yixiang.co
 * 注意：
 * 本软件为www.yixiang.co开发研制，未经购买不得使用
 * 购买后可获得全部源代码（禁止转卖、分享、上传到码云、github等开源平台）
 * 一经发现盗用、分享等行为，将追究法律责任，后果自负
 */
package co.yixiang.modules.activity.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.api.YshopException;
import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.common.utils.QueryHelpPlus;
import co.yixiang.dozer.service.IGenerator;
import co.yixiang.enums.BillDetailEnum;
import co.yixiang.enums.PayTypeEnum;
import co.yixiang.enums.ShopCommonEnum;
import co.yixiang.exception.BadRequestException;
import co.yixiang.modules.activity.domain.YxUserExtract;
import co.yixiang.modules.activity.param.UserExtParam;
import co.yixiang.modules.activity.service.YxUserExtractService;
import co.yixiang.modules.activity.service.dto.YxUserExtractDto;
import co.yixiang.modules.activity.service.dto.YxUserExtractQueryCriteria;
import co.yixiang.modules.activity.service.mapper.YxUserExtractMapper;
import co.yixiang.modules.commom.domain.YxAppdict;
import co.yixiang.modules.commom.service.YxAppdictService;
import co.yixiang.modules.user.domain.YxAuthentication;
import co.yixiang.modules.user.domain.YxUser;
import co.yixiang.modules.user.domain.YxUserBank;
import co.yixiang.modules.user.domain.YxUserinfo;
import co.yixiang.modules.user.service.*;
import co.yixiang.utils.FileUtil;
import co.yixiang.utils.RedisUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;


/**
* @author hupeng
* @date 2020-05-13
*/
@Service
@AllArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class YxUserExtractServiceImpl extends BaseServiceImpl<YxUserExtractMapper, YxUserExtract> implements YxUserExtractService {

    private final IGenerator generator;
    private final YxUserExtractMapper yxUserExtractMapper;
    private final YxUserService userService;
    private final YxUserinfoService yxUserinfoService;
    private final YxUserBillService billService;
    private final YxUserBankService yxUserBankService;
    private final RedisUtils redisUtil;
    private final YxAppdictService yxAppdictService;
    private final YxAuthenticationService yxAuthenticationService;


    /**
     * 开始提现
     * @param userInfo 用户
     * @param param UserExtParam
     */
    @Override
    public void userExtract(YxUser userInfo, UserExtParam param) {

        YxUserinfo yxUserinfo = yxUserinfoService.selectByUserId(userInfo.getUid());
        BigDecimal extractPrice = BigDecimal.ZERO;
        double money = 0;
        //判断是否是10的倍数
        BigDecimal dividePrice = new BigDecimal(param.getMoney()).divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
        if (new BigDecimal(dividePrice.intValue()).compareTo(dividePrice) != 0) throw new YshopException("提现到手续费必须是10的倍数");

        if(param.getType() == 1){ //余额

            extractPrice = userInfo.getNowMoney();
            if(extractPrice.compareTo(BigDecimal.ZERO) <= 0) throw new YshopException("提现手续费不足");

            money = Double.valueOf(param.getMoney());
            if( extractPrice.compareTo(BigDecimal.valueOf(money)) < 0) throw new YshopException("提现手续费不足");
            if(money < 100) throw new YshopException("提现手续费大于100");

        }else if(param.getType() == 2){ //佣金

            extractPrice = userInfo.getBrokeragePrice();
            if(extractPrice.compareTo(BigDecimal.ZERO) <= 0) throw new YshopException("提现佣金不足");

            money = Double.valueOf(param.getMoney());
            if( extractPrice.compareTo(BigDecimal.valueOf(money)) < 0) throw new YshopException("提现佣金不足");

            if(money < 100) throw new YshopException("提现佣金大于100");

        }

        double balance = NumberUtil.sub(extractPrice.doubleValue(),money);
        if(balance < 0) balance = 0;

        if(!PayTypeEnum.TB.getValue().equals(param.getExtractType())){
            YxUserExtract userExtract = new YxUserExtract();
            userExtract.setUid(userInfo.getUid());
            userExtract.setExtractType(param.getExtractType());
            userExtract.setType(param.getType());
            userExtract.setExtractPrice(new BigDecimal(param.getMoney()));
            userExtract.setRealPrice(new BigDecimal(param.getMoney()));
            BigDecimal decimal = new BigDecimal(String.valueOf(redisUtil.get("dict:tixianshouxufei")));
            userExtract.setRealPrice(new BigDecimal(param.getMoney())
                    .subtract(new BigDecimal(param.getMoney()).multiply(decimal))
                    .setScale(2 , BigDecimal.ROUND_HALF_UP));
            userExtract.setBalance(BigDecimal.valueOf(balance));
            userExtract.setCardImgae(param.getCardImgae());
            if(StrUtil.isNotEmpty(param.getName())){
                userExtract.setRealName(param.getName());
            }else {
                userExtract.setRealName(userInfo.getNickname());
            }

            if(StrUtil.isNotEmpty(param.getWeixin())){
                userExtract.setWechat(param.getWeixin());
            }else {
                userExtract.setWechat(userInfo.getNickname());
            }

            String mark = "";

            if(PayTypeEnum.ALI.getValue().equals(param.getExtractType())){
                if(0==yxUserinfo.getBindZfb()){
                    throw new YshopException("请先绑定支付宝");
                }
                mark = "提现至支付宝"+param.getMoney()+"元";
            }else if(PayTypeEnum.WEIXIN.getValue().equals(param.getExtractType())){
                if(0==yxUserinfo.getBindWx()){
                    throw new YshopException("请先绑定微信");
                }
                mark = "提现至微信"+param.getMoney()+"元";
            }else if(PayTypeEnum.BANK.getValue().equals(param.getExtractType())){
                if(0==yxUserinfo.getBindBank()){
                    throw new YshopException("请先绑定银行卡");
                }
                mark = "提现至银行卡"+param.getMoney()+"元";
            }

            yxUserExtractMapper.insert(userExtract);
            //更新佣金
            YxUser yxUser = new YxUser();
            yxUser.setUid(userInfo.getUid());

            if(param.getType() == 1){ // 余额
                redisUtil.set("UserPrice"+yxUser.getUid(),BigDecimal.valueOf(balance)
                        .setScale(2 , BigDecimal.ROUND_HALF_UP));
                yxUser.setNowMoney(BigDecimal.valueOf(balance));

                //插入流水
                billService.expend(userInfo.getUid(),"提现", BillDetailEnum.CATEGORY_1.getValue(),
                        BillDetailEnum.TYPE_4.getValue(),money,balance, mark);
            }else if(param.getType() == 2){ //佣金
                yxUser.setBrokeragePrice(BigDecimal.valueOf(balance));

                //插入流水
                billService.expend(userInfo.getUid(),"提现", BillDetailEnum.CATEGORY_4.getValue(),
                        BillDetailEnum.TYPE_4.getValue(),money,balance, mark);
            }
            userService.updateById(yxUser);

        }else {
            //更新佣金
            YxUser yxUser = new YxUser();
            yxUser.setUid(userInfo.getUid());
            YxAppdict tx = yxAppdictService.getOne(new QueryWrapper<YxAppdict>().lambda().eq(YxAppdict::getCode, "tixiandaoTB"));
            BigDecimal sxf ;
            if (ObjectUtil.isEmpty(tx)) sxf = new BigDecimal("0.1");
            else sxf = new BigDecimal(tx.getMemo());
            BigDecimal multiply = new BigDecimal(param.getMoney()).subtract(new BigDecimal(param.getMoney()).multiply(sxf));
            //当前用户金额
            BigDecimal nowPrice = new BigDecimal(String.valueOf(redisUtil.get("UserPrice" + yxUser.getUid())));
            yxUser.setNowMoney(nowPrice.add(multiply).setScale(2, BigDecimal.ROUND_HALF_UP));
            yxUser.setBrokeragePrice(BigDecimal.valueOf(balance));
            userService.updateById(yxUser);
            //修改redis
            redisUtil.set("UserPrice"+yxUser.getUid() , nowPrice.add(multiply).setScale(2, BigDecimal.ROUND_HALF_UP));
            //插入流水余额
            billService.expend(userInfo.getUid(),"提现至手续费", BillDetailEnum.CATEGORY_4.getValue(),
                    BillDetailEnum.TYPE_4.getValue(),money,balance, "提现至手续费");
            //插入流水余额
            billService.income(userInfo.getUid(),"佣金提现至手续费", BillDetailEnum.CATEGORY_1.getValue(),
                    BillDetailEnum.TYPE_4.getValue(),multiply.doubleValue(),userInfo.getNowMoney().add(multiply).doubleValue(),
                    "提现至手续费"+param.getMoney()+"元" ,"");
        }



    }

    /**
     * 累计提现金额
     * @param uid uid
     * @return double
     */
    @Override
    public double extractSum(Long uid) {
        return yxUserExtractMapper.sumPrice(uid);
    }


    //==============================================================//

    @Override
    //@Cacheable
    public Map<String, Object> queryAll(YxUserExtractQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        PageInfo<YxUserExtractDto> page = new PageInfo<>(queryAll(criteria));
        for (YxUserExtractDto yxUserExtractDto:page.getList()
             ) {
            YxUserinfo yxUserinfo =yxUserinfoService.selectByUserId(yxUserExtractDto.getUid());
            YxAuthentication yxAuthentication =yxAuthenticationService.getOne(new QueryWrapper<YxAuthentication>().lambda()
                .eq(YxAuthentication::getUid,yxUserExtractDto.getUid()).eq(YxAuthentication::getStatus,1));
            YxUser yxUser = userService.getById(yxUserExtractDto.getUid());
            if(null !=yxAuthentication){
                yxUserExtractDto.setNickName(yxAuthentication.getRealName());
            }else{
                yxUserExtractDto.setNickName(yxUser.getNickname());
            }
            //支付宝
            if ("1".equals(yxUserExtractDto.getExtractType())) {
                yxUserExtractDto.setName(yxUserinfo.getZhifubaoName());
                yxUserExtractDto.setAccount(yxUserinfo.getZhifubaoAccount());
                yxUserExtractDto.setCode(yxUserinfo.getZhifubaoCode());
                //微信
            } else if ("2".equals(yxUserExtractDto.getExtractType())){
                yxUserExtractDto.setName(yxUserinfo.getWeixinName());
                yxUserExtractDto.setAccount(yxUserinfo.getWeixinAccount());
                yxUserExtractDto.setCode(yxUserinfo.getWeixinCode());
            }  else if ("4".equals(yxUserExtractDto.getExtractType())) {
                List<YxUserBank> yxUserBanks=yxUserBankService.selectAllByUserId(yxUserExtractDto.getUid());
                if(yxUserBanks.size()>0){
                    yxUserExtractDto.setName(yxUserBanks.get(0).getRealName());
                    yxUserExtractDto.setAccount(yxUserBanks.get(0).getBankNumber());
                    yxUserExtractDto.setCode(yxUserBanks.get(0).getImage());
                    yxUserExtractDto.setBankName(yxUserBanks.get(0).getBankName());
                }
            }
        }
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", generator.convert(page.getList(), YxUserExtractDto.class));
        map.put("totalElements", page.getTotal());
        return map;
    }


    @Override
    //@Cacheable
    public List<YxUserExtractDto> queryAll(YxUserExtractQueryCriteria criteria){
        return baseMapper.selectUserExList(criteria);
//        return baseMapper.selectList(QueryHelpPlus.getPredicate(YxUserExtract.class, criteria));
    }


    @Override
    public void download(List<YxUserExtractDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (YxUserExtractDto yxUserExtract : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put(" uid",  yxUserExtract.getUid());
            map.put("名称", yxUserExtract.getRealName());
            map.put("bank = 银行卡 alipay = 支付宝wx=微信", yxUserExtract.getExtractType());
            map.put("银行卡", yxUserExtract.getBankCode());
            map.put("开户地址", yxUserExtract.getBankAddress());
            map.put("支付宝账号", yxUserExtract.getAlipayCode());
            map.put("提现金额", yxUserExtract.getExtractPrice());
            map.put(" mark",  yxUserExtract.getMark());
            map.put(" balance",  yxUserExtract.getBalance());
            map.put("无效原因", yxUserExtract.getFailMsg());
            map.put(" failTime",  yxUserExtract.getFailTime());
            map.put("-1 未通过 0 审核中 1 已提现", yxUserExtract.getStatus());
            map.put("微信号", yxUserExtract.getWechat());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    /**
     * 操作提现
     * @param resources YxUserExtract
     */
    public void doExtract(YxUserExtract resources){
        if(resources.getStatus() == null){
            throw new BadRequestException("请选择审核状态");
        }

        if(ShopCommonEnum.EXTRACT_0.getValue().equals(resources.getStatus())){
            throw new BadRequestException("请选择审核状态");
        }
        if(ShopCommonEnum.EXTRACT_MINUS_1.getValue().equals(resources.getStatus())){
            if(StrUtil.isEmpty(resources.getFailMsg())){
                throw new BadRequestException("请填写失败原因");
            }

            YxUserExtract userExtract = this.getById(resources.getId());
            YxUser yxUser = userService.getById(resources.getUid());
            if(userExtract.getType() == ShopCommonEnum.YJ.getValue()){
                String mark = "提现失败,退回手续费"+resources.getExtractPrice()+"元";
                double balance = NumberUtil.add(yxUser.getBrokeragePrice(),resources.getExtractPrice()).doubleValue();
                //插入流水
                billService.income(resources.getUid(),"提现失败", BillDetailEnum.CATEGORY_4.getValue(),
                        BillDetailEnum.TYPE_4.getValue(),resources.getExtractPrice().doubleValue(),balance,
                        mark,resources.getId().toString());

                //返回提现金额
                userService.incBrokeragePrice(resources.getExtractPrice(),resources.getUid());
            }else {
                String mark = "提现失败,退回手续费"+resources.getExtractPrice()+"元";
                BigDecimal nowPrice = new BigDecimal(String.valueOf(redisUtil.get("UserPrice" + yxUser.getUid())));
                double balance = NumberUtil.add(nowPrice,resources.getExtractPrice()).doubleValue();
                //插入流水
                billService.income(resources.getUid(),"提现失败", BillDetailEnum.CATEGORY_1.getValue(),
                        BillDetailEnum.TYPE_4.getValue(),resources.getExtractPrice().doubleValue(),balance,
                        mark,resources.getId().toString());

                //返回提现金额
                userService.incNowPrice(resources.getExtractPrice(),resources.getUid());

                redisUtil.set("UserPrice" + yxUser.getUid() , new BigDecimal(balance).setScale(2 , BigDecimal.ROUND_HALF_UP));
            }

            resources.setFailTime(new Date());

        }

        this.saveOrUpdate(resources);
    }
}
